package com.unei.guava.demo.collection

import com.google.common.base.Function
import com.google.common.base.Predicate
import com.google.common.base.Predicates
import com.google.common.collect.ArrayListMultimap
import com.google.common.collect.BiMap
import com.google.common.collect.FluentIterable
import com.google.common.collect.HashBasedTable
import com.google.common.collect.HashBiMap
import com.google.common.collect.HashMultimap
import com.google.common.collect.ImmutableListMultimap
import com.google.common.collect.Iterables
import com.google.common.collect.Lists
import com.google.common.base.Joiner
import com.google.common.collect.Maps
import com.google.common.collect.Ordering
import com.google.common.collect.Sets
import com.google.common.collect.Range
import com.google.common.collect.Multimap
import com.google.common.primitives.Ints
import com.unei.guava.demo.fp.City

/**
 * Created by SunLei on 2015/2/9.
 */

//java
Person person1=new Person("Wilma","Fintston",30,"F");
Person person2=new Person("Fred","Flintstone",32,"M");
Person person3=new Person("Betty","Rubble",31,"F");
Person person4=new Person("Barney","Rubble",33,"M");
//newArrayList 创建一个新的List
List<Person> personList= Lists.newArrayList(person1,person2,person3,person4);

//Guava FluentIterable from,filter,contains
Iterable<Person> personsFilteredByAge = FluentIterable
        .from(personList)   //创建一个iterable的包装类型FluentItable
        //filter 将Predicate绑定到每个元素，在调用contains等方法时进行调用
        .filter(new Predicate<Person>() {
    @Override
    boolean apply(Person person) {
        return person.getAge() > 31;
    }
});

//groovy
println Iterables.contains(personsFilteredByAge,person2)
println Iterables.contains(personsFilteredByAge,person1)
println Iterables.contains(personsFilteredByAge,person3)
println Iterables.contains(personsFilteredByAge,person4)

//java
//Guava FluentIterable from transform
//将personList的元素通过Function处理后，生成新的list
List<String> transformPersonList = FluentIterable
        .from(personList)
        .transform(new Function<Person, String>() {
    @Override
    String apply(Person input) {
        return Joiner.on(':').join(input.getName(),input.getAge());
    }
}).toList();

//groovy
println transformPersonList.get(0);
println personList.size()

//java
//Guava Lists
println "guava lists-------------------------"
//将personList均分为每个子list大小为2的嵌套list
List<List<Person>> subList=Lists.partition(personList,2)
println subList.size()
println subList.get(0).size()


//Guava Sets
println "guava sets---------------------"
Set<String> s1=Sets.newHashSet("1","2","3")
Set<String> s2=Sets.newHashSet("2","3","4")
//difference 返回在s1中存在，但不在s2中存在的元素
Set<String> s3=Sets.difference(s1,s2)
s3.each {print it}
println()

//Sets.symmetricDifference 返回在一个set中存在，但不在另一个set中存在的元素，
Set<String> s4=Sets.symmetricDifference(s1,s2)
s4.each{print it+"\t"}
println()

//Sets.intersection 返回set的交集
Set<String> s5=Sets.intersection(s1,s2)
s5.each{print it+"\t"}
println()

//Sets.union 返回set的并集
Set<String> s6=Sets.union(s1,s2)
s6.each{print it+"\t"}
println()

//Maps
public List<Book> getBooks(){
    List<Book> books=Lists.newArrayList()
    books.add(new Book("book1"))
    books.add(new Book("book2"))
    books.add(new Book("book3"))
    books.add(new Book("book4"))
    return books
}

List<Book> books=getBooks()
//Maps.uniqueIndex iterator 产生map的value,Function 的结果作为map的key
Map<String,Book> bookMap= Maps.uniqueIndex(books.iterator(),new Function<Book,String>(){
    @Override
    String apply(Book input) {
        return input.getIsbn()
    }
})
bookMap.each {println it.key+":"+it.value}

//Maps.asMap books产生map的key,Function产生map的value
Map<Book,String> asBookMap=Maps.asMap(Sets.newHashSet(books),new Function<Book,String>(){
    @Override
    String apply(Book input){
        return input.getIsbn()
    }
})
println asBookMap.size()
asBookMap.each {println it.key.toString()+":"+it.value}

//Maps.toMap 返回一个不可变的map
Map<Book,String> immutableMap=Maps.toMap(Sets.newHashSet(books),new Function<Book,String>(){
    @Override
    String apply(Book input) {
        return input.getIsbn()
    }
})

asBookMap.each {println it.key.toString()+":"+it.value}

//ArrayListMultimap
//一个key对应多个值，key:ArrayList 格式,支持一个key对应重复的值
ArrayListMultimap<String,String> multiMap=ArrayListMultimap.create();
multiMap.put("Foo","1")
multiMap.put("Foo","2")
multiMap.put("Foo","3")
multiMap.put("Foo","3")
multiMap.each {print it.get("Foo")}
println()

//HashMultimap
//一个key对应多个值，key:HashMap 格式，一个key对应的值不能重复
HashMultimap<String,String> hashMultiMap=HashMultimap.create()
hashMultiMap.put("Foo","1")
hashMultiMap.put("Foo","2")
hashMultiMap.put("Foo","3")
hashMultiMap.each {print it.get("Foo")}

//BiMap
//一个value只能有一个key
BiMap<String,String> biMap=HashBiMap.create()
biMap.put("1","Tom")
//biMap.put("2","Tom")

//BiMap.forcePut 替换掉具有相同value的key
biMap.forcePut("2","Tom")
biMap.each{println it.key+":"+it.value}

//BiMap.inverse key value互换
println("BiMap.inverse--------------")
BiMap<String,String> inverseBiMap=biMap.inverse()
inverseBiMap.each{println it.key+":"+it.value}

//HashBasedTable
println "HashBasedTable------------------"
//创建一个行数为2，列数为2的table
//HashBasedTable<R,C,V> R 行name/id，C cell name/id，V cell value
HashBasedTable<Integer,String,String> table=HashBasedTable.create(2,2)
table.put(1,"name","haha")
table.put(1,"age","10")
table.put(2,"name","gogo")
table.put(2,"age","20")
table.rowKeySet().each{println table.get(it,"name")+":"+table.get(it,"age")}

println "Range---------------------------"
//创建一个指定范围的区间
//包括开始和结束值
Range<Integer> range=Range.closed(1,10)
//不包括开始和结束值
Range<Integer> open=Range.open(1,10)
//判断是否包含开始和结束值
println range.contains(1).toString()+"--"+range.contains(10)
println open.contains(1).toString()+"--"+open.contains(10)

//Range  设置边界的方法
//openClosed,closedOpen,greaterThan,atLeast,lessThan,atMost

//通过Range和Function创建一个Predicate，根据Range对数据进行过滤判断
Range<Integer> ageRange=Range.closed(30,32)
Function<Person,Integer> ageFunction=new Function<Person, Integer>() {
    @Override
    Integer apply(Person input) {
        return input.getAge()
    }
}

Predicate<Person> predicate=Predicates.compose(ageRange,ageFunction)
println predicate.apply(person1)

//Immutable collection
Multimap<Integer,String> map=new ImmutableListMultimap.Builder<Integer,String>().put(1,"Foo").putAll(2,"ho","ha","hi").build()

map.keySet().each {println map.get(it)}


//Ordering
class CityByPopluation implements Comparator<City>{
    @Override
    int compare(City o1, City o2) {
        return Ints.compare(o1.getPopulation(),o2.getPopulation())
    }
}

//倒序
CityByPopluation cityByPopluation=new CityByPopluation()
Ordering.from(cityByPopluation).reverse()

//排序时，如果碰到null值，则将null值放到第一个
Ordering.from(cityByPopluation).nullsFirst()

//获取最大值最小值
List<City> cityList=Lists.newArrayList()
Ordering<City> ordering=Ordering.from(cityByPopluation)
List<City> topFive=ordering.greatestOf(cityList,5) //获取最大的5个
List<City> bottomThree=ordering.leastOf(cityList,3) //获取最小的三个